package controller.entitiesManagement;

import java.awt.Color;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

import controller.algorithms.AlgorithmManager;
import controller.taskManagement.Task;

import reference.codes.CodeTask;
import reference.constants.ConstantProblem;
import reference.constants.ConstantProgram;

import utilities.clock.Clock;
import utilities.clock.ClockListener;
import view.completeView.entityView.EntityListener;

public class Entity implements ClockListener {
	private ArrayList<EntityListener> m_listeners;
	private int m_posX;
	private int m_posY;
	private boolean m_isWorking;
	private Task m_currentTask;
	
	private double m_speed;
	private HashMap<Integer, Double> m_abilityToWork;
	
	public Entity(){
		m_listeners = new ArrayList<EntityListener>();
		m_abilityToWork = new HashMap<Integer, Double>();
		setRandomValue();
		setWorking(false);
		Clock.getClock().addClockListener(this);
	}
	
	public void acts() {
		AlgorithmManager.getInstance().getAlgorithm().nextStepEntity(this);
	}

	public void setClock(Clock this_clock) {
		
	}

	private void setRandomValue(){
		Random random = new Random();
		setPosX(random.nextInt(ConstantProblem.GROUND_WIDTH*ConstantProblem.BLOCK_SIZE-ConstantProgram.ENTITY_WIDTH));
		setPosY(random.nextInt(ConstantProblem.GROUND_HEIGHT*ConstantProblem.BLOCK_SIZE-ConstantProgram.ENTITY_WIDTH));
		m_speed = random.nextInt(ConstantProblem.ENTITY_MAX_SPEED-ConstantProblem.ENTITY_MIN_SPEED)+ConstantProblem.ENTITY_MIN_SPEED;
		int codesTask[] = CodeTask.getAllTasks();
		for(int i=0;i<codesTask.length;i++){
			m_abilityToWork.put(codesTask[i], random.nextDouble()%ConstantProblem.ABILITY_MAX/2);
		}
	}
	
	public void move(int new_pos_x, int new_pos_y){
		m_posX = new_pos_x;
		m_posY = new_pos_y;
		for(EntityListener listener : m_listeners){
			listener.move(new_pos_x, new_pos_y);
		}
	}
	
	public void headPosition(int pos_x, int pos_y){
		double deltaX = pos_x-m_posX;
		double deltaY = pos_y-m_posY;
		if(deltaX!=0.0 || deltaY!=0.0){
			double vectorLength = Math.sqrt((deltaX*deltaX)+(deltaY*deltaY));
			deltaX *= m_speed/vectorLength;
			deltaY *= m_speed/vectorLength;	
			this.move(new Double(m_posX+deltaX).intValue(), new Double(m_posY+deltaY).intValue());
		}
	}
	
	public boolean performTask(Task task){
		boolean result = task.perform(2.0);
		if(!result){
			m_currentTask = null;
		}
		return result;
	}
	
	public Color getDefaultColor(){
		return Color.BLACK;
	}

	public int getPosX() {
		return m_posX;
	}

	public void setPosX(int m_posX) {
		this.m_posX = m_posX;
	}

	public int getPosY() {
		return m_posY;
	}

	public void setPosY(int m_posY) {
		this.m_posY = m_posY;
	}

	public boolean isWorking() {
		return m_isWorking;
	}

	public void setWorking(boolean m_isWorking) {
		this.m_isWorking = m_isWorking;
	}
	
	public void addEntityListener(EntityListener listener){
		m_listeners.add(listener);
	}
	
	public void removeEntityListener(EntityListener listener){
		m_listeners.remove(listener);
	}

	public Task getCurrentTask() {
		return m_currentTask;
	}

	public void setCurrentTask(Task m_currentTask) {
		this.m_currentTask = m_currentTask;
	}
	
	public double getAbilityToWork(int code_task){
		if(m_abilityToWork!=null && m_abilityToWork.get(new Integer(code_task))!=null)
			return m_abilityToWork.get(new Integer(code_task)).doubleValue();
		return 0.0;
	}
	
	public void modifyAbilityToWork(int code_task, double delta_ability){
		double currentAbility = m_abilityToWork.get(new Integer(code_task)).doubleValue();
		currentAbility += delta_ability;
		if(currentAbility<0)
			currentAbility = 0;
		if(currentAbility>ConstantProblem.ABILITY_MAX)
			currentAbility = ConstantProblem.ABILITY_MAX;
		m_abilityToWork.put(new Integer(code_task), new Double(currentAbility));
	}
}
